<?php

namespace MMC\Statistics\BaiDu;

class LoginService extends AbstractService
{
    public function preLogin()
    {
        $this->httpConnect->init($this->config, self::LOGIN_URL);

        $preLoginData = array(
            'username'      => $this->config->getUserName(),
            'token'         => $this->config->getToken(),
            'functionName'  => 'preLogin',
            'uuid'          => $this->config->getUUID(),
            'request'       => array(
                'osVersion' => 'windows',
                'deviceType' => 'pc',
                'clientVersion' => '1.0',
            ),
        );

        $response = $this->httpConnect->post($preLoginData);

        if (0 === $response['code']) {
            $data   = $this->gzDecode($response['data'], strlen($response['data']));
            $result = json_decode($data, true);

            if (!isset($result['needAuthCode']) || $result['needAuthCode'] === true) {
                throw new \Exception("[error] preLogin return data format error: {$data}");
            }

            if ($result['needAuthCode'] === false) {
                return true;
            }

            throw new \Exception("[error] unexpected preLogin return data: {$data}");

        }

        throw new \Exception("[error] preLogin unsuccessfully with return code: {$response['code']}");
    }


    public function doLogin()
    {
        $this->httpConnect->init($this->config, self::LOGIN_URL);

        $doLoginData = array(
            'username'      => $this->config->getUserName(),
            'token'         => $this->config->getToken(),
            'functionName'  => 'doLogin',
            'uuid'          => $this->config->getUUID(),
            'request'       => array(
                'password' => $this->config->getPassword(),
            ),
        );

        $response = $this->httpConnect->post($doLoginData);

        if (0 === $response['code']) {
            $data = gzinflate(substr($response['data'], 10, -8));
            $result = json_decode($data, true);

            if (!isset($result['retcode']) || !isset($result['ucid']) || !isset($result['st'])) {
                throw new \Exception("[error] doLogin return data format error:{$data} ");
            }

            if (0 === $result['retcode']) {
                return array(
                    'ucid'  => $result['ucid'],
                    'st'    => $result['st'],
                );
            }

            throw new \Exception("[error] doLogin unsuccessfully with retcode:{$result['retcode']}");
        }

        throw new \Exception("[error] doLogin unsuccessfully with return code: {$response['code']}");
    }


    public function doLogout($userId, $st)
    {
        $this->httpConnect->init($this->config, self::LOGIN_URL);

        $doLogoutData = array(
            'username'      => $this->config->getUserName(),
            'token'         => $this->config->getToken(),
            'functionName'  => 'doLogin',
            'uuid'          => $this->config->getUUID(),
            'request'       => array(
                'ucid' => $userId,
                'st'   => $st,
            ),
        );

        $response = $this->httpConnect->post($doLogoutData);

        if (0 === $response['code']) {

            $data = gzdecode($response['data'], strlen($response['data']));
            $result = json_decode($data, true);

            if (!isset($result['retcode'])) {
                throw new \Exception("[error] doLogout return data format error:{$data}" );
            }

            if (0 === $result['retcode']) {
                return true;
            }

            throw new \Exception(" doLogout unsuccessfully with retcode: {$result['retcode']}" );
        }

        throw new \Exception("[error] doLogout unsuccessfully with return code:{$response['code']} ");
    }


    public static function gzDecode($data)
    {
        $flags = ord(substr($data, 3, 1));

        $headerLen = 10;
        $extraLen  = 0;

        if ($flags & 4) {
            $extraLen = unpack('v' ,substr($data, 10, 2));
            $extraLen = $extraLen[1];
            $headerLen += 2 + $extraLen;
        }

        if ($flags & 8) {
            $headerLen = strpos($data, chr(0), $headerLen) + 1;
        }

        if ($flags & 16) {
            $headerLen = strpos($data, chr(0), $headerLen) + 1;
        }

        if ($flags & 2) {
            $headerLen += 2;
        }

        $unpacked = @gzinflate(substr($data, $headerLen));

        if ($unpacked === FALSE) {
            $unpacked = $data;
        }

        return $unpacked;
    }

}